//
// Created by 86155 on 2025/4/16.
//

#include "FeAsmPrinter.h"
#include "MCTargetDesc/FeMCTargetDesc.h"
#include "llvm/MC/TargetRegistry.h"
#include "TargetInfo/FeTargetInfo.h"
#include "MCTargetDesc/FeMCExpr.h"
using namespace llvm;

#define DEBUG_TYPE "asm-printer"

#define PRINT_ALIAS_INSTR
#include "FeGenMCPseudoLowering.inc"

bool FeAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
  AsmPrinter::runOnMachineFunction(MF);
  return true;
}

//发射指令
void FeAsmPrinter::emitInstruction(const MachineInstr *MI) {
  if (emitPseudoExpansionLowering(*OutStreamer, MI)) {
    return;
  }
  MCInst TmpInst;
  lowerToMCInst(MI, TmpInst);
  EmitToStreamer(*OutStreamer, TmpInst);
}

/*
 * 1. 确定偏移的指令条数    √
 * 2. 去除上下文的标号    √
 */
//符号操作数的转换
MCOperand FeAsmPrinter::lowerSymbolOperand(const MachineInstr *MI, const MachineOperand &MO) const {
  const MCSymbol *symbol = nullptr;
  FeMCExpr::Kind kind = FeMCExpr::BIAO;
  symbol = MO.getMBB()->getSymbol(); //获取该基本块对应的汇编标签
  unsigned instructionNumberNow = 0;
  unsigned instructionNumberArrive = 0;
  bool foundNow = false;
  bool foundArrive = false;
  const MachineFunction *MF = MI->getParent()->getParent();

  //需要跳过去的目标标号所在行数
  for (const auto &MBB : *MF) {
    for (const auto &I : MBB) {
      instructionNumberArrive++;
      if(MBB.getSymbol()->getName() == MO.getMBB()->getSymbol()->getName()){
        foundArrive = true;
        break;
      }
    }
    if (foundArrive) break;
  }

  //目前指令所在行数
  for (const auto &MBB : *MF) {
    for (const auto &I : MBB) {
      instructionNumberNow++;
      if (&I == MI) {
        foundNow = true;
        break;
      }
    }
    if (foundNow) break;
  }

  unsigned short num = instructionNumberArrive-instructionNumberNow;
  const MCExpr *Expr = MCSymbolRefExpr::create(symbol, OutContext);
  Expr = new FeMCExpr(kind,Expr,num);
  return MCOperand::createExpr(Expr);
}


void FeAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &Out) {
  Out.setOpcode(MI->getOpcode());
//  if(MI->getOpcode() == Fe::CALL){
//    printf("%d\n",MI->getOpcode());
//  }
  //操作数的转换
  for (const MachineOperand &MO : MI->operands()) {
    MCOperand MCOp; //输出
    switch (MO.getType()) {
    case MachineOperand::MO_Register: {//寄存器
      MCOp = MCOperand::createReg(MO.getReg());
      break;
    }
    case MachineOperand::MO_Immediate: {//立即数
      MCOp = MCOperand::createImm(MO.getImm());
      break;
    }
    case MachineOperand::MO_MachineBasicBlock: {//基本块
      MCOp = lowerSymbolOperand(MI,MO);
      break;
    }
    case MachineOperand::MO_GlobalAddress: {
      auto *symbol = getSymbol(MO.getGlobal());
      const auto &expr =
          MCSymbolRefExpr::create(symbol, MCSymbolRefExpr::VK_None, OutContext);
      MCOp = MCOperand::createExpr(expr);
      break;
    }
    case MachineOperand::MO_RegisterMask: {
      /// Ignore
      break;
    }
    default:
      llvm_unreachable("unkown operand type");
    }
    Out.addOperand(MCOp);
  }
}
void FeAsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) {
  // 原标签输出逻辑（注释掉或按需调整）
  // printLabel(BB.getName());
}
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeFeAsmPrinter() {
  RegisterAsmPrinter<FeAsmPrinter> X(getFeTarget());
}